#!/usr/bin/env python

"""
        __author__      = "Vishal Patil"
        __copyright__   = "Copyright (C) 2006 Vishal Patil"
"""

import random
from pgap import BaseGeneticOperator

#
#	This class implements the crossover and mutation operations on a 
#	population of chromosones. The user of this class can set the
#	Crossover and mutation rate	
#

class CrossoverMutateOperator(BaseGeneticOperator.BaseGeneticOperator):
	
	#
	#	Set the crossover and mutation rates to default values
	#
	def __init__(self):
		self.crossOverRate = 10 
		self.mutationRate  = 2		
	#
	#	Set the crossover rate
	#	
	def setCrossOverRate(self,crossOverRate):
		self.crossOverRate = int(crossOverRate)
	
	#
	#	Set the mutation rate
	#
	def setMutationRate(self,mutationRate):
		self.mutationRate = int(mutationRate)
	
	#
	#	Perform the crossover and mutation operations on the population
	#	of chromosones as per the crossover and mutation rate
	#
	def operate(self,population):

		iteration = 0
		chromosones = population.getChromosones()
		chromosoneCount = len(chromosones)

		populationSize = population.getPopulationSize()
		
		if chromosoneCount == 0:
			raise "Empty chromosone list"	

		geneCount   = len(chromosones[0].genes)
			
		while (iteration < populationSize):

			if (random.randint(1,100) % int(100/self.crossOverRate)):
				p1 = random.choice(chromosones)
				p2 = random.choice(chromosones)
			
				pivot = random.randint(0,geneCount - 1)
				
				child1genes = []
				child2genes = []

				child1Chromosone = p1.clone()
				child2Chromosone = p2.clone()

  				for index in range(0,pivot):
			                child1genes.append(p1.genes[index].clone())
			                child2genes.append(p2.genes[index].clone())

			        for index in range(pivot,geneCount):
			                child1genes.append(p2.genes[index].clone())
			                child2genes.append(p1.genes[index].clone())
				
				child1Chromosone.setGenes(child1genes)
				child2Chromosone.setGenes(child2genes)

				if (random.randint(1,100) % int(100/self.mutationRate)):
					child1Chromosone.mutate()
					child2Chromosone.mutate()

				newChromosones = []
				newChromosones.append(child1Chromosone)
				newChromosones.append(child2Chromosone)

				chromosones = chromosones + newChromosones

			iteration = iteration + 1

		return chromosones

